#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
增量车辆文件移动脚本
从 chuhai_scraper/storage/vehicles/picknbuy24 移动到 F:\0109_repository\gitee_repository\storage\vehicles\picknbuy24
确保不覆盖现有文件，仅进行增量更新
"""

import os
import shutil
import logging
from pathlib import Path
from typing import Dict, List, Tuple
from datetime import datetime


class IncrementalVehicleMover:
    """增量车辆文件移动器"""
    
    def __init__(self):
        # 源目录
        self.source_dir = Path(r"F:\0109_repository\gitee_repository\chuhai\chuhai_scraper\storage\vehicles\picknbuy24")
        # 目标目录
        self.target_dir = Path(r"F:\0109_repository\gitee_repository\storage\vehicles\picknbuy24")
        
        # 设置日志
        self._setup_logging()
        
        # 统计信息
        self.stats = {
            'moved_files': 0,
            'skipped_files': 0,
            'created_dirs': 0,
            'errors': 0
        }
    
    def _setup_logging(self):
        """设置日志记录"""
        # 获取脚本所在目录的父目录（即 chuhai_scraper 目录）
        script_dir = Path(__file__).parent
        project_dir = script_dir.parent
        log_dir = project_dir / "logs"
        log_dir.mkdir(exist_ok=True)
        
        log_file = log_dir / f"vehicle_move_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
        
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler(log_file, encoding='utf-8'),
                logging.StreamHandler()
            ]
        )
        self.logger = logging.getLogger(__name__)
    
    def validate_directories(self) -> bool:
        """验证源目录和目标目录"""
        if not self.source_dir.exists():
            self.logger.error(f"源目录不存在: {self.source_dir}")
            return False
        
        if not self.source_dir.is_dir():
            self.logger.error(f"源路径不是目录: {self.source_dir}")
            return False
        
        # 创建目标目录（如果不存在）
        try:
            self.target_dir.mkdir(parents=True, exist_ok=True)
            self.logger.info(f"目标目录已准备: {self.target_dir}")
        except Exception as e:
            self.logger.error(f"无法创建目标目录 {self.target_dir}: {e}")
            return False
        
        return True
    
    def scan_files(self) -> Dict[str, List[Path]]:
        """扫描源目录中的所有文件"""
        files_by_dir = {}
        
        try:
            for root, dirs, files in os.walk(self.source_dir):
                if files:  # 只处理包含文件的目录
                    root_path = Path(root)
                    relative_path = root_path.relative_to(self.source_dir)
                    
                    file_paths = []
                    for file in files:
                        file_path = root_path / file
                        if file_path.is_file():
                            file_paths.append(file_path)
                    
                    if file_paths:
                        files_by_dir[str(relative_path)] = file_paths
            
            total_files = sum(len(files) for files in files_by_dir.values())
            self.logger.info(f"扫描完成，发现 {len(files_by_dir)} 个目录，共 {total_files} 个文件")
            
        except Exception as e:
            self.logger.error(f"扫描源目录时出错: {e}")
            
        return files_by_dir
    
    def move_file_safely(self, source_file: Path, target_file: Path) -> bool:
        """安全移动单个文件"""
        try:
            # 检查目标文件是否已存在
            if target_file.exists():
                # 比较文件大小，如果相同则跳过
                if source_file.stat().st_size == target_file.stat().st_size:
                    self.logger.debug(f"文件已存在且大小相同，跳过: {target_file.name}")
                    self.stats['skipped_files'] += 1
                    return True
                else:
                    # 文件存在但大小不同，生成新文件名
                    base_name = target_file.stem
                    suffix = target_file.suffix
                    counter = 1
                    
                    while True:
                        new_name = f"{base_name}_{counter}{suffix}"
                        new_target = target_file.parent / new_name
                        if not new_target.exists():
                            target_file = new_target
                            break
                        counter += 1
                    
                    self.logger.info(f"文件已存在但大小不同，重命名为: {target_file.name}")
            
            # 确保目标目录存在
            target_file.parent.mkdir(parents=True, exist_ok=True)
            
            # 移动文件
            shutil.move(str(source_file), str(target_file))
            self.logger.debug(f"成功移动: {source_file.name} -> {target_file}")
            self.stats['moved_files'] += 1
            return True
            
        except Exception as e:
            self.logger.error(f"移动文件失败 {source_file} -> {target_file}: {e}")
            self.stats['errors'] += 1
            return False
    
    def move_directory_files(self, relative_dir: str, files: List[Path]) -> None:
        """移动指定目录下的所有文件"""
        target_subdir = self.target_dir / relative_dir
        
        # 创建目标子目录
        try:
            target_subdir.mkdir(parents=True, exist_ok=True)
            if not target_subdir.exists():
                self.stats['created_dirs'] += 1
            self.logger.info(f"处理目录: {relative_dir} ({len(files)} 个文件)")
        except Exception as e:
            self.logger.error(f"无法创建目录 {target_subdir}: {e}")
            return
        
        # 移动文件
        for source_file in files:
            target_file = target_subdir / source_file.name
            self.move_file_safely(source_file, target_file)
    
    def cleanup_empty_directories(self) -> None:
        """清理空的源目录"""
        try:
            for root, dirs, files in os.walk(self.source_dir, topdown=False):
                root_path = Path(root)
                
                # 跳过根目录
                if root_path == self.source_dir:
                    continue
                
                # 如果目录为空，删除它
                try:
                    if not any(root_path.iterdir()):
                        root_path.rmdir()
                        self.logger.info(f"删除空目录: {root_path.relative_to(self.source_dir)}")
                except OSError:
                    # 目录不为空，跳过
                    pass
                    
        except Exception as e:
            self.logger.error(f"清理空目录时出错: {e}")
    
    def run(self) -> bool:
        """执行增量移动操作"""
        self.logger.info("=" * 50)
        self.logger.info("开始增量车辆文件移动操作")
        self.logger.info(f"源目录: {self.source_dir}")
        self.logger.info(f"目标目录: {self.target_dir}")
        self.logger.info("=" * 50)
        
        # 验证目录
        if not self.validate_directories():
            return False
        
        # 扫描文件
        files_by_dir = self.scan_files()
        if not files_by_dir:
            self.logger.info("没有找到需要移动的文件")
            return True
        
        # 移动文件
        for relative_dir, files in files_by_dir.items():
            self.move_directory_files(relative_dir, files)
        
        # 清理空目录
        self.cleanup_empty_directories()
        
        # 输出统计信息
        self.logger.info("=" * 50)
        self.logger.info("移动操作完成！")
        self.logger.info(f"移动文件: {self.stats['moved_files']}")
        self.logger.info(f"跳过文件: {self.stats['skipped_files']}")
        self.logger.info(f"创建目录: {self.stats['created_dirs']}")
        self.logger.info(f"错误数量: {self.stats['errors']}")
        self.logger.info("=" * 50)
        
        return self.stats['errors'] == 0


def main():
    """主函数"""
    print("车辆文件增量移动脚本")
    print("=" * 50)
    
    # 确认操作
    print(f"源目录: F:\\0109_repository\\gitee_repository\\chuhai\\chuhai_scraper\\storage\\vehicles\\picknbuy24")
    print(f"目标目录: F:\\0109_repository\\gitee_repository\\storage\\vehicles\\picknbuy24")
    print("\n此操作将:")
    print("1. 将源目录下的所有文件移动到目标目录")
    print("2. 保持原有目录结构")
    print("3. 不会覆盖现有文件（相同大小跳过，不同大小重命名）")
    print("4. 移动完成后清理空的源目录")
    
    response = input("\n确认执行此操作吗？(y/N): ").strip().lower()
    if response not in ['y', 'yes']:
        print("操作已取消")
        return
    
    # 执行移动操作
    mover = IncrementalVehicleMover()
    success = mover.run()
    
    if success:
        print("\n✅ 移动操作成功完成！")
    else:
        print("\n❌ 移动操作过程中出现错误，请查看日志文件")


if __name__ == "__main__":
    main()
